KuruWrap = {}

ResTypes = {
    NINE_SIXTEEN = 1,
    THREE_FOUR = 2,
    ONE_ONE = 3,
    OHTER = 4
}

function KuruWrap.addNodeAndRelease(scene,node)
    scene:addNode(node)
    node:release()
    return node
end

function KuruWrap.addChildAndRelease(parent,node)
    parent:addNode(node)
    node:release()
    return node
end

--control nodes in array show or hide
function KuruWrap.showAllNodes(nodes,show)
    for i=1,#nodes do
        nodes[i]:setEnabled(show)
    end
end

-- show group nodes
function KuruWrap.showGroupNodes(nodes,group)
    for i=1,#nodes do
        for j=1,#nodes[i]do
            nodes[i][j]:setEnabled(i==group)
        end
    end
end

function KuruWrap.addNodeWithConfig(scene,config)
    local node = KuruWrap.addNodeAndRelease(scene,KuruWrap.getNodeWithConfig(config))
    return node
end

function KuruWrap.addNodesWithConfig(scene,config)
    local nodes={}
    for i=1,#config do
        nodes[i] = KuruWrap.addNodeWithConfig(scene,config[i])
    end

    return nodes
end

-- add nodes base on configuration
function KuruWrap.addGroupNodesWithConfig(scene,nodesconfig)
    local nodes={}
    for i=1,#nodesconfig do
        nodes[i] = {}
        for j=1,#nodesconfig[i] do
          local cfg = nodesconfig[i][j]
          local node = KuruWrap.addNodeAndRelease(scene,KuruWrap.getNodeWithConfig(cfg))
          table.insert(nodes[i],node)
        end
    end

    return nodes
end

function KuruWrap.addNodesToFrameBufferWithConfig(framebuffer,nodesconfig)
    local nodes = {}
    for i=1,#nodesconfig do
        local cfg = nodesconfig[i]
        nodes[i] = KuruWrap.addChildAndRelease(framebuffer,KuruWrap.getNodeWithConfig(cfg))
    end

    return nodes
end

-- get node with config
function KuruWrap.getNodeWithConfig(config)
    local node = nil
    if(config.type == 0)then
        node = getBgNode(config.path,config.scale,config.anchor,config.stretch,config.tx,config.ty,config.blendmode)
    elseif(config.type == 1)then
        node = getStickerNode(config.path,config.scale,config.location,config.anchor,config.tx,config.ty,0,config.flip,config.blendmode,config.fps)
    elseif(config.type == 2)then
        node = getSkinExNode(config.path,config.blendmode)
    elseif(config.type == 3)then
        node =getSkinNode(config.path,config.blendmode)
    elseif(config.type == 4)then
        node = getColorLensNode(config.path,config.blendmode)
    elseif(config.type == 5)then
        node = getFloatingNode(config.path,config.x,config.y,config.width,config.height,config.fps,config.blendmode)
    elseif(config.type == 6)then
        node = getFilterNode(config.path,config.intensity,config.filterName)
    elseif(config.type == 7)then
        node = KaleFaceDistortionNode.createWithPath(BASE_DIRECTORY .. config.path)
    elseif(config.type == 8)then
        node = KuruBodyStickerNode.create(BASE_DIRECTORY .. config.path, config.blendmode, -1, -1)
        node:setLocationType(config.locationType)
        node:setRotationType(config.rotationType)
        if config.anchorType ~= nil then
            node:setAnchorType(config.anchorType)
        end
        if config.degree ~= nil then
            node:setRotationByDegree(Vector3.create(0, 0, config.degree));
        end
        if(config.roty~=nil) then
            node:setRotationByDegree(Vector3.create(0, config.roty, 0));
        end
        node:setAnchorOffset(config.tx, config.ty)
        node:setScale(config.scale_x, config.scale_y, 1)
    else
        -- do nothing
    end
    return node
end
  
function getSkinExNode(filePath, blendMode)
    local skinExBuilder = KaleFaceSkinNodeBuilder.create()
    skinExBuilder:path(BASE_DIRECTORY .. filePath)
    skinExBuilder:skinType(KaleFaceSkinType.FACE_EX)
    skinExBuilder:blendmode(blendMode)
    skinExBuilder:skinEx(KaleFaceSkinNodeSkinEx.create():fillInMouth(true))
    skinExBuilder:build()
    return KaleFaceSkinNode.create(skinExBuilder)
end
  
function getSkinNode(filePath, blendMode)
    local skinExBuilder = KaleFaceSkinNodeBuilder.create()
    skinExBuilder:path(BASE_DIRECTORY .. filePath)
    skinExBuilder:skinType(KaleFaceSkinType.FACE)
    skinExBuilder:blendmode(blendMode)
    skinExBuilder:build()
    return KaleFaceSkinNode.create(skinExBuilder)
end
  
  
function getStickerSampler(filepath,fps)
    local sp = KuruAnimationSampler.createFromPath(BASE_DIRECTORY..filepath,false,false)
    sp:setRepeatCount(0)
    sp:setFPS(fps)
    sp:play()

    return sp
end
  
function getStickerNode(filePath, scale, loactionType, anchorType, translateX, translateY, translateZ, flip, blendMode, fps)
    local sampler = getStickerSampler(filePath, fps)
    local node = KaleStickerNode.createFromSampler(sampler, blendMode, -1, -1)
  
    if flip then
      node:setScale(-scale, scale, 0)
    else
      node:setScale(scale, scale, 0)
    end
  
    node:setId("sticker")
    node:setLocationType(loactionType)
    node:setAnchorType(anchorType)
    node:setTranslation(translateX, translateY, translateZ)
    sampler:release()
  
    return node
end
  
function getBgNode(filepath,scale,anchor,stretch,tx,ty,blendmode)
    local sampler = getStickerSampler(filepath,20)
    local node = KuruBackgroundImageNode.createFromSampler(sampler,blendmode)
    node:setAnchorType(anchor)
    node:setStretch(stretch)
    node:setScale(scale,scale,1)
    node:setTranslation(tx,ty,0)
  
    sampler:release()
    return node
end
  
function getFloatingNode(filepath,x,y,width,height,fps, blendmode)
    local sampler = getStickerSampler(filepath,fps)
    local node = KuruFloatingImageNode.createFromSampler(sampler,x,y,width,height,blendmode)
  
    sampler:release()
    return node
end
  
function getColorLensNode(path,blendmode)
    local colorLensNode = KuruColorLensNode.create(BASE_DIRECTORY .. path, blendmode)
    return colorLensNode
end

function getFilterNode(path,intensity,filterName)
    if  filterName=='None' then
        local lutNode = KuruLookUpTableFilterNode.createById(config.id,true,config.intensity)
    else
        local lutNode =  KuruLookUpTableFilterNode.create(BASE_DIRECTORY .. path, false, config.intensity)
    end
    return lutNode
end

-- create screen plane model
function KuruWrap.createFullscreenQuadModel(sampler)
    local smesh = Mesh.createQuadFullscreen()
    local model = Model.create(smesh)
    smesh:release()
  
    local material = Material.createWithShaderFile("res/shaders/passthrough.vert","res/shaders/passthrough.frag",Nil)
    material:getParameter("u_worldViewProjectionMatrix"):setMatrix(Matrix:identity()) --not u_worldViewProjectMatrix,u_worldViewProjectMatrix on ios will reverse uv's v direction  
    material:getParameter("u_texture"):setSampler(sampler)
    model:setMaterial(material,-1)
    material:release()
  
    return model
end

function KuruWrap.createFrameBufferSampler(name,width,height)
    local splitFrameBuffer = FrameBuffer.create(name, math.floor(width), math.floor(height), TextureFormat.RGBA)
    local splitFrameBufferSampler = TextureSampler.createWithTexture(splitFrameBuffer:getRenderTarget(0):getTexture())
    splitFrameBufferSampler:setWrapMode(TextureWrap.CLAMP, TextureWrap.CLAMP)

    return splitFrameBuffer,splitFrameBufferSampler
end

function KuruWrap.setFrame(width,height)
    KuruWrap.resType = KuruWrap.getResType(width,height)
end

function KuruWrap.isFrameChanged()

    local kuruEngine = KuruEngine.getInstance()
    local resl = kuruEngine:getResolution()
    local ret = KuruWrap.getResType(resl.x, resl.y)
    
    if(KuruWrap.resType == nil or KuruWrap.resType ~= ret)then
        KuruWrap.resType = ret
        return true
    else
        return false
    end
end

function KuruWrap.getResType(x,y)
    local ret = ResTypes.OHTER
    local kuruEngine = KuruEngine.getInstance()
    local config = kuruEngine:getCameraConfig()

    local curAspect = x / y
  
    local E = 0.01
    
    if not config:isGalleryMode() then
      if 9/16 - E < curAspect and curAspect < 9/16 + E then
        ret = ResTypes.NINE_SIXTEEN
  
      elseif 3/4- E < curAspect and curAspect < 3/4 + E then
        if KuruEngine.getInstance():getCameraConfig():isOneToOne() then
          ret = ResTypes.ONE_ONE
        else
          ret = ResTypes.THREE_FOUR
        end
      end
  
    else -- 갤러리모드
      if 9/16 - E < curAspect and curAspect < 9/16 + E then
        ret = ResTypes.NINE_SIXTEEN
  
      elseif 3/4 - E < curAspect and curAspect < 3/4 + E then
        ret = ResTypes.THREE_FOUR
      
      elseif 1 - E < curAspect and curAspect < 1 + E then
        ret = ResTypes.ONE_ONE
      
      else
        ret = ResTypes.OHTER
      end
    end

    return ret
end